<!doctype html>
<html lang=ru id=faq>


<title>OpenBSD Порты: Отличие от других BSD проектов</title>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="../../openbsd.css">
<link rel="canonical" href="https://www.openbsd.org/faq/ports/differences.html">

<h2 id=OpenBSD>
<a href="../../index.html">
<i>Open</i><b>BSD</b></a>
Порты - Отличие от других BSD проектов
<small>
<a href="index.html">[Порты - На главную]</a>
</small>
</h2>
<hr>

<ul>
  <li><a href="#Extra"          >Дополнительная помощь</a>
  <li><a href="#Generic"        >Общие вопросы по поводу инфраструктуры</a>
  <li><a href="#Make"           >Правильное использование make</a>
  <li><a href="#Fetch"          >Распаковка (извлечение) исходников</a>
  <li><a href="#wrkdir"         >Инфраструктура <code>WRKDIR</code></a>
  <li><a href="#Fake"           >Fake установка порта</a>
    <ul>
     <li><a href="#Introduction">Введение</a>
     <li><a href="#Advantages"  >Преимущества</a>
     <li><a href="#How"         >Как это сделать</a>
     <li><a href="#Pitfalls"    >Ловушки</a>
    </ul>
  <li><a href="#Tools"          >Packaging инструменты</a>
  <li><a href="#Flavors"        >Flavors</a>
</ul>

<hr>

<h2 id="Extra">Дополнительная помощь</h2>

Инфраструктура портирования включает в себя несколько скриптов, которые
находятся в <code>infrastructure/bin</code>. Они предназначены для упрощения
процесса создания новых портов:

<dl>
<dt>check-lib-depends
    <dd>Запускается при помощи <code>make lib-depends-check</code> с целью
    проверки shared libraries зависимостей.
<dt>update-patches
    <dd>Запускается при помощи <code>make update-patches</code>, который
    <b>всегда</b> должен использоваться для обновления/регенерации патчей.
<dt>update-plist
    <dd>Запускается при помощи <code>make update-plist</code>.
    Этот скрипт позаботится о аккуратности packing-lists. OpenBSD packing-lists
    значительно отличаются от своих сородичей из других проектов BSD, отчасти
    потому, что packaging инструменты в ней были полностью переписаны.
</dl>

Проверьте каталог <code>infrastructure/bin</code>, если вы ищете другие полезные
скрипты. Для большинства из них есть man-страницы.

<h2 id="Generic">Общие вопросы по поводу инфраструктуры</h2>

<a href="https://man.openbsd.org/make">make(1)</a> в OpenBSD поддерживает
<code>${VAR:U}</code> и <code>${VAR:L}</code> для преобразования значения
переменной в верхний или нижний регистр. Другими словами, make test может
быть запущен независимо от регистра. Например:

<pre class="cmdbox">
.if ${NEED_XXX:L} == "yes"
do stuff if yes
.else
do other stuff
.endif
</pre>

Теоретически, все bool-переменные, распознаваемые <code>bsd.port.mk</code>,
всегда должны быть определены, поэтому в констукциях кода наподобее
<code>defined(USE_FOO)</code> нет необходимости, и
<code>${USE_FOO:L} != "no"</code> должен работать.

<p>
Основной файл <code>bsd.port.mk</code> был сильно оптимизирован и исправлен.
В частности, он может выполнять задачи параллельно.
Из-за этого была утрачена функция <code>scripts/{pre,do,post}-*</code>.
Чтобы снова воспользоваться этой функцией, запустите скрипт вручную из
<code>Makefile</code>.

<h2 id="Make">Правильное использование make</h2>

Обратите внимание, что если вы запускаете make с параметром (например вот так
<code><b>make VAR=value</b></code>), присваиваемое значение параметра
переопределяет/перезаписывает значение, которое присваивается <code>VAR</code>
из <code>Makefile</code>.
Это означает, что нет необходимости в множестве патчей для <code>Makefile</code>.
Гораздо лучше правильно установить значение <code>MAKE_FLAGS</code>,
что к тому же снизит и maintanance нагрузку.

<h2 id="Fetch">Распаковка (извлечение) исходников</h2>

Существует два типа архивов с исходниками: <code>DISTFILES</code> и
<code>PATCHFILES</code>.
OpenBSD обрабатывает их одинаковым способом и по умолчанию загружает все
из <code>MASTER_SITES</code>. Здесь <b>нет</b> ни <code>PATCH_SITES</code>,
ни <code>PATCH_SITES_SUBDIR</code>.

<p>
Если все загружаемые файлы не принадлежат одному и тому же набору сайтов,
OpenBSD разрешает расширение <code>filename:0</code> до <code>filename:9</code>,
и в этом случае для извлечения файлов будет использоваться
<code>MASTER_SITES0</code> вплоть до <code>MASTER_SITES9</code>.

<p>
Некоторым платформам могут понадобиться специфичные distfiles.
В прошлом это вызывало проблемы, связанные с зеркалированием distfiles.
Теперь же OpenBSD поддерживает третий набор файлов: <code>SUPDISTFILES</code>.
Они используются только для создания checksums и для зеркалирования
(mirroring). Обратите внимание, что <code>SUPDISTFILES</code> может
перекрываться <code>DISTFILES</code> или <code>PATCHFILES</code>.
Например:

<pre class="cmdbox">
DISTFILES=foo-1.0.tgz
.if ${ARCH} == "i386"
DISTFILES+=foo-i386.tgz
.elif ${ARCHI} == "amd64"
DISTFILES+=foo-amd64.tgz
.endif
SUPDISTFILES=foo-i386.tgz foo-amd64.tgz
</pre>

<h2 id="wrkdir">Инфраструктура <code>WRKDIR</code></h2>

Нам не нужны порты, которые используют <code>NO_WRKDIR</code>.
Все порты OpenBSD должны иметь рабочий каталог.
Детали, касательно имени рабочего каталога, не должны вызывать беспокойства
у того, кто собирает порт. Если вам нужно узнать об этом имени, спросите
<code>Makefile</code>:

<pre class="cmdbox">
$ <b>cd that_ports_dir &amp;&amp; make show=WRKDIR</b>
</pre>

Эта команда покажет значение <code>WRKDIR</code> (т.е. имя рабочего
каталога) порта.

<p>
Основная причина этого запрета заключается в том, что <code>bsd.port.mk</code>
в OpenBSD действует как настоящий <code>Makefile</code> с зависимостями.
Этап <code>fetch</code> зависит от distfiles и patchfiles, а все остальные
этапы зависят от реальных файлов, находящихся в рабочем каталоге, поэтому
они не могут существовать без рабочего каталога.

<p>
Если <code>DISTFILES</code> extraction является особенным, установите

<pre class="cmdbox">
EXTRACT_ONLY=
</pre>

и сделайте extraction на этапе <code>post-extract.</code>.

<p>
<dl>
<dt><code>WRKDIR</code></dt>

<dd>Рабочий каталог порта, куда он помещает свои собственные cookies.</dd>

<dt><code>WRKDIST</code></dt>

<dd>Подкаталог <code>WRKDIR</code>, куда фактически распаковывается порт.
    Это также базовый каталог для патча.
    Другие BSD в настоящее время не имеют <code>WRKDIST/WRKSRC</code> различий
    и имеют только <code>WRKSRC</code>.</dd>

<dt><code>WRKSRC</code></dt>

<dd>Подкаталог <code>WRKDIST</code>, в котором фактический находятся исходники.</dd>

<dt><code>WRKBUILD</code></dt>

<dd>Подкаталог <code>WRKDIR</code>, в котором будут выполняться конфигурирование
    и сборка порта.
    Другие BSD не имеют <code>WRKBUILD/WRKSRC</code> различий.
    Программы, основанные на autoconf (в основном), обычно могут установить
    <code>SEPARATE_BUILD</code>, чтобы позволить сборке порта происходить в
    <code>WRKBUILD</code>, отличном от <code>WRKSRC</code>.</dd>

<dt><code>WRKCONF</code></dt>

<dd>Подкаталог <code>WRKDIR</code>, в котором должны запускаться configure скрипты.
    По умолчанию используется <code>WRKBUILD</code>, что в 99% случаев верно.</dd>

<dt><code>WRKINST</code></dt>

<dd>Каталог, в который будет установлен порт перед созданием пакета
    (читайте о «Fake установке портов» ниже).</dd>
</dl>

<p>
<i>Обратите внимание, что <code>NO_WRKSUBDIR</code>  был удален: теперь этот же эффект
можно достигнуть установив <code>WRKDIST=$(WRKDIR)</code>.</i>

<h2 id="Fake">Fake установка порта</h2>

<h3 id="Introduction">Введение</h3>

После завершения сборки другие BSD приступают к установке порта, а затем
собирают пакет из установленного порта.
OpenBSD использует fake установку вместо этого.

<ul>
<li>Порт OpenBSD сконфигурирован и собран как обычно (т.е. установлен в
    <code>PREFIX</code>, обычно это <code>/usr/local</code>).

<li>Но указывается сдалать установку в другое место, а именно в <code>WRKINST</code>,
    который обычно является подкаталогом <code>WRKDIR</code>.

<li>Затем из fake установки создается пакет. Происходит это при помощи pkg_create
    опции <code>-B</code>.

<li>Наконец, получившийся пакет может быть установлен при помощи pkg_add.
</ul>

<h3 id="Advantages">Преимущества</h3>

<ul>
<li>Для того, кто собирает пакет (package builder), это означает, что большинство
    портов не нужно устанавливать на самом деле, что устраняет огромное количество
    потенциальных проблем с неправильно установленными портами.
    Это также позволяет создавать несколько конфликтующих пакетов на одном компьютере.
    Наконец, это позволяет создавать новый набор непроверенных пакетов без правильной
    установки.

<li>Для того, кто составляет порт (port writer), это значительно упрощает задачу поиска
    проблем в packing lists, поскольку fake среда пуста до установки порта.
    Кроме того, если порт устанавливает слишком много файлов, больше нет необходимости
    настраивать установку порта: достаточно просто не записывать посторонние файлы в
    packing list.

<li>Для пользователя (end user) это улучшает качество пакетов: поскольку последний порт
    устанавливается с помощью pkg_add, пользователь получает <i>точно такое же</i>
    программное обеспечение, которое было подготовлено на машине того, кто собирал порт
    (porter).
</ul>

<h3 id="How">Как это сделать</h3>

Цели, используемые для <code><b>make fake</b></code>, являются обычными целями для
установки, за исключением нескольких отличий:

<ul>
<li>Вместо <code>MAKE_FLAGS</code> используется	<code>FAKE_FLAGS</code>.
    По умолчанию <code>FAKE_FLAGS</code> устанавливает <code>DESTDIR=${WRKINST}</code>.

<li>Вместо <code>INSTALL_TARGET</code> используется <code>FAKE_TARGET</code>.

<li>Во время выполнения <code>{pre,do,post}-install</code>, значение
<code>TRUEPREFIX</code> установлено как <code>$(PREFIX)</code>,
<code>PREFIX</code> установлено как <code>$(WRKINST)$(PREFIX)</code>, а
<code>DESTDIR</code> установлено как <code>$(WRKINST)</code>.
</ul>

<p>
Порты, использующие imake, должны работать как и обычно, поскольку цели imake
настроены на использование <code>DESTDIR</code>. Точно так же недавние порты
конфигурации GNU не нуждаются ни в каких изменениях.

<p>
Еще один хороший прием - "late binding" («поздняя привязка»): настройте порты на
использование prefix со значением <code>$(DESTDIR)/usr/local</code>, чтобы
получившийся <code>Makefile</code> имел следующую конфигурацию:

<pre class="cmdbox">
prefix=$(DESTDIR)/usr/local
</pre>

Когда порт начинает собираться при пустом значении <code>DESTDIR</code>,
будет использоваться <code>/usr/local</code>.
Fake установка поместит все в <code>${WRKINST}/usr/local</code> (например, для
GNU configure используйте <code>CONFIGURE_STYLE= gnu dest</code>).

<h3 id="Pitfalls">Ловушки</h3>

<ul>
<li>Некоторые порты несовместимы с изменениями значения своего <code>DESTDIR</code>:
    для бОльшей части порта это не будет проблемой, за исключением одного или двух
    нарушителей. Исправьте проблему (Patch the problem away).

<li>Будьте внимательны и отслеживайте фактическое местоположение, в котором
    установлен порт, и местоположение, используемое конфигами пакета.
    Это очень легко пропустить, но легко исправить при помощи <code>TRUEPREFIX</code>.

<li>Абсолютные symlinks всегда нужно настраивать.
    К счастью, <code>bsd.port.mk</code> заметит проблемы в этой области.

<li>Некоторые порты не хотят оставлять в покое <code>$(DESTDIR)</code> на этапе
    настройки. Тут понадобится <code>post-configure</code>, который добавляет
    <code>DESTDIR</code> настройки во все Makefile-файлы.

<li>Очень редко порт сопротивляется всем разумным попыткам использовать FAKE.
    Подход грубой силы работает тут на ура: используйте <code>pre-fake</code>,
    чтобы слинковать или скопировать все, что порт хочет найти в <code>WRKINST</code>,
    затем выполните install в chroot.
</ul>

<h2 id="Tools">Packaging инструменты</h2>

Инструменты пакета знают о довольно многих типах файлов и могут делать многое
автоматически: в большинстве случаев команды <code>@exec</code> или скрипты
<code>INSTALL</code> не нужны.

<p>
Обратите внимание, что все ненужные скрипты должны быть заблокированы,
так как они имеют проблемы с масштабируемостью.
Гораздо проще отлаживать инфраструктуру одного пакета, чем модифицировать
сотни скриптов для решения новых проблем.
Например:

<ul>
<li><code>@exec ldconfig</code> не нужен, поскольку shared libraries упоминаются
    как <code>@lib libfoo.so.1.0</code>, а <code>ldconfig</code> запускается
    только при необходимости и корректно обрабатывает chroot.

<li><code>@exec install-info</code> не нужен, поскольку файлы документации info
    упоминаются как <code>@info file.info</code>. Благодаря этому нет проблем и
    с составными info файлами, а также отпадает необходимость в запуске
    <code><b>makeinfo --no-split</b></code>.

<li>шрифты (fonts) интегрируются автоматически благодаря
   <code>@font</code> и <code>@fontdir</code>.

<li>Новые пользователи и группы создаются при помощи <code>@newuser</code>
    и <code>@newgroup</code> вместо installation скриптов.
    Они создаются достаточно рано, чтобы их можно было использовать в процессе
    дальнейшего extraction пакета.

<li>Большинство third party баз данных обрабатываются при помощи <code>@tag</code>,
    который запускает такие инструменты как <code>update-desktop-database</code>
    в конце установки.

<li>Файлы конфигурации обрабатываются при помощи <code>@sample</code>
    вместо installation скриптов.
</ul>

<p>
Прочитайте <a href="https://man.openbsd.org/pkg_create">pkg_create(1)</a>, где
содержится более подробная информация по этой теме.
В большинстве случаев, <code><b>make update-plist</b></code> создаст очень хорошую
приблизительную картину того, что должно быть в packing-list и скопирует настройки
из одной версии в другую (следующую).


<h2 id="Flavors">Flavors</h2>

Параметры сборки были организованны (рационализированы) в виде Flavors, так
что сборка пакетов теперь может быть последовательной.
Порт с параметрами должен установить <code>FLAVORS</code> в качестве списка
всех параметров, которые имеют смысл для этого порта (например,
<code>FLAVORS=foo bar zoinx</code>), а затем использовать <code>FLAVOR</code>,
чтобы проверить, какие параметры фактически были выбраны (например,
<code>FLAVOR=zoinx foo</code>).
<code>bsd.port.mk</code> предоставляет тут некоторую поддержку:

<ul>
<li><code>PKGNAME</code> настроен для включения опций, разделенных дефисом
    (например, <code>package-foo-zoinx</code>).

<li><code>WRKDIR</code> настроен таким образом, что различные flavors могут
    собираться одновременно, не мешая при этом друг другу.

<li>Конструкции вида <code>%%flavor%%</code> вызовут включение <code>PFRAG.flavor</code>.

<li><code>bsd.port.subdir.mk</code> понимает расширение
    <code>SUBDIR=directory,opt1,opt2</code> и интерпретирует его как «надо
    собрать порт в <code>directory</code> с <code>FLAVOR=opt1 opt2</code>».
</ul>

<p>
Проверить, что тот или иной flavor был выбран для сбоки, можно следующим образом:

<pre class="cmdbox">
.if ${FLAVOR:Mzoinx}
</pre>

Существует дополнительное расширение, известное как <code>MULTI_PACKAGES</code>.
Вообще говоря, <code>MULTI_PACKAGES</code> и <code>FLAVORS</code> являются
противоположными механизмами.
Вместе их количество в дереве портов OpenBSD несколько меньше, чем в другиех BSD,
поскольку они позволяют из одного порта создавать много разных пакетов.
<a href="https://man.openbsd.org/bsd.port.mk">bsd.port.mk(5)</a> имеет
<a href="https://man.openbsd.org/bsd.port.mk#FLAVORS_AND_MULTI_PACKAGES">целый раздел</a>,
посвященный FLAVORS и MULTI_PACKAGES.
